﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO.IsolatedStorage;
using System.Diagnostics;

namespace SharpDropBoxClient.db
{
    public class PolenterMetaDataSimpleDb 
    {
        private string filePath = "db";
        private string fileName = "metaDataDB.ser";
        private readonly PSFileInfo serializedFile = null;
        ObservableCollection<MetaDataEntry> data = new ObservableCollection<MetaDataEntry>();

        public ObservableCollection<MetaDataEntry> Data
        {
            get
            {
                return data;
            }
        }
        public void Save(MetaDataEntry saveEntry)
        {
            var entry = Data.Where(e => e.Path.Equals(saveEntry.Path, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
            if (entry != null)
            {
                var idx = Data.IndexOf(entry);
                if (idx > -1)
                {
                    Data[idx] = saveEntry;
                    IsDirty = true;
                }
            }
            else
            {
                DropBoxCacheDb.Instance.Data.Add(saveEntry);
            }
        }
        public void Delete(MetaDataEntry saveEntry)
        {
            DropBoxCacheDb.Instance.Data.Remove(saveEntry);
        }
        public void Flush()
        {
            serializeData();
        }

        public PolenterMetaDataSimpleDb()
        {
            serializedFile = new PSFileInfo(filePath + @"\" + fileName);

            data.CollectionChanged +=new System.Collections.Specialized.NotifyCollectionChangedEventHandler(data_CollectionChanged);
            try { // VS might try to run this code and then it throws weird errors.
            
                if (PSDirectory.Exists(filePath) && serializedFile.Exists)
                {
                    // Deserialize File
                    deserializeData();
                }
                else if(!PSDirectory.Exists(filePath))
                {
                    PSDirectory.CreateDirectory(filePath);
                }
            }
            catch {
            
            }
        }

        public bool IsDirty{get;set;}
        void data_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            IsDirty = true;
            //if (deserializing)
            //    return;
            //// OnChange we will serialize (for now.. there might be a better way to do this by catching application shutdown and getting it there)
            //serializeData();
        }

        public bool IsDbCorrupted { get; set; }

        private void deserializeData()
        {
            MetaDataEntry[] temp = null;
                
            try
            {
                using (var fs = serializedFile.Open(System.IO.FileMode.Open))
                {
                    temp = DatabaseSerializer.Deserialize(fs) as MetaDataEntry[];
                }
            }
            catch(Exception ex) 
            {
                IsDbCorrupted = true;
#if DEBUG
                Debug.WriteLine("Error while deserializing" + ex.ToString());
#endif
                Debug.WriteLine("In {1}.{2} tagged {3}, swallowing Error {0}", ex, "PolenterMetaDataSimpleDb", "deserializeData()", "deserialize");
            }
            if(temp != null)
            {
                deserializing = true;
                data.CollectionChanged -=new System.Collections.Specialized.NotifyCollectionChangedEventHandler(data_CollectionChanged);
                lock(data)
                {
                    data.Clear();
                    foreach (var item in temp)
	                {
                        data.Add(item);
	                }
                }
                deserializing = false;
                data.CollectionChanged +=new System.Collections.Specialized.NotifyCollectionChangedEventHandler(data_CollectionChanged);
            }

        }

        bool deserializing = false;
        private void serializeData()
        {
            if (deserializing)
                return; // Gonna skip for now
            var temp = data.ToArray();
            lock(data) {
                try
                {
                    using (var fs = serializedFile.Open(System.IO.FileMode.Create))
                    {
                        DatabaseSerializer.Serialize(temp, fs);
                    }
                    IsDirty = false;
                }
                catch(Exception ex) 
                {
                    Debug.WriteLine("In {1}.{2} tagged {3}, swallowing Error {0}", ex, "PolenterMetaDataSimpleDb", "serializeData()", "full");
                }
            }
        }
        public string DatabaseName { get; set; }

        private Polenter.Serialization.SharpSerializer _DatabaseSerializer = new Polenter.Serialization.SharpSerializer(Polenter.Serialization.BinarySerializationMode.SizeOptimized);
        public Polenter.Serialization.SharpSerializer DatabaseSerializer
        {
            get
            {
                return _DatabaseSerializer;
            }
            set
            {
                _DatabaseSerializer = value;
            }
        }

        public void  App_Exit(object sender, EventArgs e)
        {
 	        if(IsDirty)   
                serializeData();
        }

    }
}
